package com.cicadamob.contact.api.Utils.Endecryption;


import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * @author guoxc
 * @create 2009-10-22
 */
public class EndecryptionUtil {
	
	private static byte[] defaultIV = {1,2,3,4,5,6,7,8};

	private static byte chr2hex(String chr) {
		if (chr.equals("0")) {
			return 0x00;
		} else if (chr.equals("1")) {
			return 0x01;
		} else if (chr.equals("2")) {
			return 0x02;
		} else if (chr.equals("3")) {
			return 0x03;
		} else if (chr.equals("4")) {
			return 0x04;
		} else if (chr.equals("5")) {
			return 0x05;
		} else if (chr.equals("6")) {
			return 0x06;
		} else if (chr.equals("7")) {
			return 0x07;
		} else if (chr.equals("8")) {
			return 0x08;
		} else if (chr.equals("9")) {
			return 0x09;
		} else if (chr.equals("A")) {
			return 0x0a;
		} else if (chr.equals("B")) {
			return 0x0b;
		} else if (chr.equals("C")) {
			return 0x0c;
		} else if (chr.equals("D")) {
			return 0x0d;
		} else if (chr.equals("E")) {
			return 0x0e;
		} else if (chr.equals("F")) {
			return 0x0f;
		}
		return 0x00;
	}

	public static byte[] HexStringToByteArray(String s) {
		byte[] buf = new byte[s.length() / 2];
		for (int i = 0; i < buf.length; i++) {
			buf[i] = (byte) (chr2hex(s.substring(i * 2, i * 2 + 1)) * 0x10 + chr2hex(s
					.substring(i * 2 + 1, i * 2 + 2)));
		}
		return buf;
	}

	public static String getBASE64(String s) {
		if (s == null)
			return null;
		return Base64.encode(s);
	}

	public static String getBase64Ofbyte(byte[] s) {
		if (s == null)
			return null;
		return Base64.encodeBytes(s);
	}
	
	/** 将一个Base64加密串进行解密 */
	public static byte[] getByteArrayFromBase64(String s) throws Exception{
		if (s == null)
			return null;
		return Base64.decode(s);
	}
	
	/**
	 * Encrypt the data by the key.
	 * @param OriSource
	 * @return strResult
	 * @throws Exception
	 */
	public static String encryptByKey(String OriSource, String key) throws Exception {
		
		String strResult = "";
		try {
			
			Cipher c3des = Cipher.getInstance("DESede/CBC/PKCS5Padding");
			SecretKeySpec myKey = new SecretKeySpec(HexStringToByteArray(key),
					"DESede");

			IvParameterSpec ivspec = new IvParameterSpec(defaultIV);
			c3des.init(Cipher.ENCRYPT_MODE, myKey, ivspec);

			byte[] testSrc = OriSource.getBytes();
			byte[] encoded = c3des.doFinal(testSrc);
			
			strResult = getBase64Ofbyte(encoded);
			
		} catch (Exception e) {
			strResult="";
		}

		return strResult;
	}
	
	/**
	 * Decrypt the encrypted data with the key.
	 * @param strData
	 * @return strResult
	 * @throws Exception
	 */
	public static String decryptByKey(String encryptedData, String key) throws Exception {
		
		String strResult = "";
		try {
			
			Cipher c3des = Cipher.getInstance("DESede/CBC/PKCS5Padding");
			SecretKeySpec myKey = new SecretKeySpec(HexStringToByteArray(key),
					"DESede");

			IvParameterSpec ivspec = new IvParameterSpec(defaultIV);
			c3des.init(Cipher.DECRYPT_MODE, myKey, ivspec);

			byte[] s= getByteArrayFromBase64(encryptedData);
			byte[] encoded = c3des.doFinal(s);
			strResult = new String(encoded);
			
		} catch (Exception e) {
			strResult="";
		}

		return strResult;
	}
	
	/**
	 * Decrypt the encrypted data with the key.
	 * @param strData
	 * @return strResult
	 * @throws Exception
	 */
	public static String getBase64HashString(String str) throws Exception{
		
		byte[] testSrc = str.getBytes();
		MessageDigest alga = MessageDigest.getInstance("SHA-1");
		alga.update(testSrc);
		byte[] digesta = alga.digest();
		return getBase64Ofbyte(digesta);
	}
	
	
	/**
	 * Decrypt the encrypted data with the key.
	 * @param strData
	 * @return strResult
	 * @throws Exception
	 */
	public static String getAuthenicator(String sourceStr,String key) throws Exception{
		
		String strResult = "";
		try {
			Cipher c3des = Cipher.getInstance("DESede/CBC/PKCS5Padding");
			SecretKeySpec myKey = new SecretKeySpec(HexStringToByteArray(key),
					"DESede");

			IvParameterSpec ivspec = new IvParameterSpec(defaultIV);
			c3des.init(Cipher.ENCRYPT_MODE, myKey, ivspec);
			
			
			byte[] testSrc = sourceStr.getBytes();
			MessageDigest alga = MessageDigest.getInstance("SHA-1");
			alga.update(testSrc);
			byte[] digesta = alga.digest();
			byte[] encoded = c3des.doFinal(digesta);
			strResult = getBase64Ofbyte(encoded);
			
		} catch (Exception e) {
			strResult="";
		}

		return strResult;
	}
	
	/**
	 * Decrypt the encrypted data with the key.
	 * @param strData
	 * @return strResult
	 * @throws Exception
	 */
	public static String desAuthenicator(String sourceStr,String key) throws Exception{
		
		String strResult = "";
		try {
			
			Cipher c3des = Cipher.getInstance("DESede/CBC/PKCS5Padding");
			SecretKeySpec myKey = new SecretKeySpec(HexStringToByteArray(key),
					"DESede");

			IvParameterSpec ivspec = new IvParameterSpec(defaultIV);			
			
			byte[] decoded = getByteArrayFromBase64(sourceStr);
			c3des.init(Cipher.DECRYPT_MODE, myKey, ivspec);
			byte[] desdecoded = c3des.doFinal(decoded);
			MessageDigest alga = MessageDigest.getInstance("SHA-1");
			alga.update(desdecoded);
			alga.digest();
		} catch (Exception e) {
			strResult="";
		}

		return strResult;
	}
	
	public static String encode3DesAndBase64(String source, String key)
	{
		String strResult = "";
		try {
			Cipher c3des = Cipher.getInstance("DESede/CBC/PKCS5Padding");
			SecretKeySpec myKey = new SecretKeySpec(HexStringToByteArray(key),"DESede");
			IvParameterSpec ivspec = new IvParameterSpec(defaultIV);
			c3des.init(Cipher.ENCRYPT_MODE, myKey, ivspec);
			byte[] testSrc = source.getBytes("utf-8");
			byte[] encoded = c3des.doFinal(testSrc);
			strResult = getBase64Ofbyte(encoded);
		} catch (Exception e) {
			strResult="";
		}
		return strResult;
	}
	
	public static String decode3DesAndBase64(String source, String key)
	{
		String strResult = "";
		try {
			Cipher c3des = Cipher.getInstance("DESede/CBC/PKCS5Padding");
			SecretKeySpec myKey = new SecretKeySpec(HexStringToByteArray(key),"DESede");
			IvParameterSpec ivspec = new IvParameterSpec(defaultIV);			
			byte[] decoded = getByteArrayFromBase64(source);
			c3des.init(Cipher.DECRYPT_MODE, myKey, ivspec);
			byte[] desdecoded = c3des.doFinal(decoded);
			strResult = new String(desdecoded, "utf-8");
		} catch (Exception e) {
			strResult="";
		}
		return strResult;
	}
	
	/**
	 * 加密数据，使用AES
	 * 
	 * @param content 需要加密的内容
	 * @param password 加密密码
	 * @return
	 */
	public static String encryptAesAndBase64( String content, String password )
	{
		try
		{
			KeyGenerator kgen = KeyGenerator.getInstance( "AES" );
			kgen.init( 128, new SecureRandom( password.getBytes() ) );
			SecretKey secretKey = kgen.generateKey();
			byte[] enCodeFormat = secretKey.getEncoded();
			SecretKeySpec key = new SecretKeySpec( enCodeFormat, "AES" );
			Cipher cipher = Cipher.getInstance( "AES" );// 创建密码器
			byte[] byteContent = content.getBytes( "utf-8" );
			cipher.init( Cipher.ENCRYPT_MODE, key );// 初始化
			byte[] result = cipher.doFinal( byteContent );
			return getBase64Ofbyte( result ); // 加密
		} catch ( NoSuchAlgorithmException e )
		{
			e.printStackTrace();
		} catch ( NoSuchPaddingException e )
		{
			e.printStackTrace();
		} catch ( InvalidKeyException e )
		{
			e.printStackTrace();
		} catch ( UnsupportedEncodingException e )
		{
			e.printStackTrace();
		} catch ( IllegalBlockSizeException e )
		{
			e.printStackTrace();
		} catch ( BadPaddingException e )
		{
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 解密数据，使用AES
	 * 
	 * @param content 待解密内容
	 * @param password 解密密钥
	 * @return
	 */
	public static String decryptBase64AndAes( String content, String password )
	{
		try
		{
			KeyGenerator kgen = KeyGenerator.getInstance( "AES" );
			kgen.init( 128, new SecureRandom( password.getBytes() ) );
			SecretKey secretKey = kgen.generateKey();
			byte[] enCodeFormat = secretKey.getEncoded();
			SecretKeySpec key = new SecretKeySpec( enCodeFormat, "AES" );
			Cipher cipher = Cipher.getInstance( "AES" );// 创建密码器
			cipher.init( Cipher.DECRYPT_MODE, key );// 初始化
			byte[] cont = getByteArrayFromBase64( content );
			byte[] result = cipher.doFinal( cont );
			return new String(result); // 加密
		} catch ( NoSuchAlgorithmException e )
		{
			e.printStackTrace();
		} catch ( NoSuchPaddingException e )
		{
			e.printStackTrace();
		} catch ( InvalidKeyException e )
		{
			e.printStackTrace();
		} catch ( IllegalBlockSizeException e )
		{
			e.printStackTrace();
		} catch ( BadPaddingException e )
		{
			e.printStackTrace();
		} catch ( Exception e )
		{
			e.printStackTrace();
		}
		return null;
	}
}